﻿/*
 * Imigrasi SMS (Special built for Immigration Office)
 * Copyright (C) 2010 Wish Enterprise Development Team

 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * Contact Us:
 * Author   : Khoirul Imamudin
 * E-Mail   : contact@wishenterprise.com     Website: http://www.wishenterprise.com
 * 
 * */

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using SmsAutorespond.Properties;
using SmsEntity.Local;
using SmsEntity.Xlink;
using SmsRepository;
using SmsRepository.Local;
using SmsRepository.Xlink;

namespace SmsAutorespond
{
    /// <summary>
    /// MainWindow
    /// </summary>
    public partial class MainWindow : Form
    {
        /// <summary>
        /// InboxNonService Base
        /// </summary>
        private InboxNonServiceBase _dbInboxNonService;

        /// <summary>
        /// InboxService Base
        /// </summary>
        private InboxServiceBase _dbInboxService;

        /// <summary>
        /// Outbox Base
        /// </summary>
        private OutboxBase _dbOutbox;

        /// <summary>
        /// XLPassportForm Base
        /// </summary>
        private XLPassportFormBase _dbPassport;

        /// <summary>
        /// Workflows
        /// </summary>
        private List<Workflow> _workflows;

        /// <summary>
        /// Initializes a new instance of the <see cref="MainWindow"/> class.
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            // initialzie connection
            StartConnection();

            // Interval
            InitializeTimeInterval();

            // load config
            LoadSmsdrc();

        }

        /// <summary>
        /// Initializes the time interval.
        /// </summary>
        private void InitializeTimeInterval()
        {
            tmrTime.Interval = Settings.Default.CheckInterval*60000;
            gr1.Text = string.Format("Progress [ Interval : {0} minute(s) ]", Settings.Default.CheckInterval);
        }

        /// <summary>
        /// Loads the SMSDRC.
        /// </summary>
        private void LoadSmsdrc()
        {
            try
            {
                var sr = new StreamReader("smsdrc");
                string line = sr.ReadLine();

                while (line != null)
                {

                    line = sr.ReadLine();

                    if (line == null) continue;

                    bool bIsDisabled = line.Trim().Substring(0, 1) == "#";
                    string[] aLine = line.Split('=');

                    switch (aLine[0].Replace("#", "").ToLower().Trim())
                    {
                        case "pin":
                            chkPIN.Checked = !bIsDisabled;
                            txtPin.Text = aLine[1].Trim();
                            break;
                        case "logfile":
                            chkLogFile.Checked = !bIsDisabled;
                            txtLogFile.Text = aLine[1].Trim();
                            break;
                        case "commtimeout":
                            chkCommTimeOut.Checked = !bIsDisabled;
                            txtCommTimeOut.Text = aLine[1].Trim();
                            break;
                        case "sendtimeout":
                            chkSendTimeOut.Checked = !bIsDisabled;
                            txtSendTimeOut.Text = aLine[1].Trim();
                            break;
                        case "receivefrequency":
                            chkReceiveFrequency.Checked = !bIsDisabled;
                            txtReceiveFrequency.Text = aLine[1].Trim();
                            break;
                        case "resetfrequency":
                            chkResetFrequency.Checked = !bIsDisabled;
                            txtResetFrequency.Text = aLine[1].Trim();
                            break;
                        case "deliveryreport":
                            chkDeliveryReport.Checked = !bIsDisabled;
                            switch (aLine[1].Trim())
                            {
                                case "no":
                                    cboDeliveryReport.SelectedIndex = 0;
                                    break;
                                case "log":
                                    cboDeliveryReport.SelectedIndex = 1;
                                    break;
                                default:
                                    cboDeliveryReport.SelectedIndex = 2;
                                    break;
                            }

                            break;
                        case "phoneid":
                            chkPhoneId.Checked = !bIsDisabled;
                            txtPhoneId.Text = aLine[1].Trim();
                            break;
                        case "user":
                            txtUser.Text = aLine[1].Trim();
                            break;
                        case "password":
                            txtPassword.Text = aLine[1].Trim();
                            break;
                        case "pc":
                            txtPC.Text = aLine[1].Trim();
                            break;
                        case "database":
                            txtDatabase.Text = aLine[1].Trim();
                            break;
                    }
                }

                sr.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, @"Error!",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Updates the SMSDRC.
        /// </summary>
        private void UpdateSmsdrc()
        {
            try
            {
                var sw = new StreamWriter("smsdrc");
                sw.WriteLine("[smsd]");
                sw.WriteLine(string.Format("{0}pin = {1}", chkPIN.Checked ? "" : "#", txtPin.Text.Trim()));
                sw.WriteLine(string.Format("{0}logfile = {1}", chkLogFile.Checked ? "" : "#", txtLogFile.Text.Trim()));
                sw.WriteLine(string.Format("{0}commtimeout = {1}", chkCommTimeOut.Checked ? "" : "#",
                                           txtCommTimeOut.Text.Trim()));
                sw.WriteLine(string.Format("{0}sendtimeout = {1}", chkSendTimeOut.Checked ? "" : "#",
                                           txtSendTimeOut.Text.Trim()));
                sw.WriteLine(string.Format("{0}receivefrequency = {1}", chkReceiveFrequency.Checked ? "" : "#",
                                           txtReceiveFrequency.Text.Trim()));
                sw.WriteLine(string.Format("{0}resetfrequency = {1}", chkResetFrequency.Checked ? "" : "#",
                                           txtResetFrequency.Text.Trim()));
                sw.WriteLine(string.Format("{0}deliveryreport = {1}", chkDeliveryReport.Checked ? "" : "#",
                                           cboDeliveryReport.Text.Trim()));
                sw.WriteLine(string.Format("{0}phoneid = {1}", chkPhoneId.Checked ? "" : "#", txtPhoneId.Text.Trim()));
                sw.WriteLine(string.Format("{0}user = {1}", chkUser.Checked ? "" : "#", txtUser.Text.Trim()));
                sw.WriteLine(string.Format("{0}password = {1}", chkPassword.Checked ? "" : "#", txtPassword.Text.Trim()));
                sw.WriteLine(string.Format("{0}pc = {1}", chkPC.Checked ? "" : "#", txtPC.Text.Trim()));
                sw.WriteLine(string.Format("{0}database = {1}", chkDatabase.Checked ? "" : "#", txtDatabase.Text.Trim()));
                sw.Close();
                MessageBox.Show(@"SMSDRC Successfully updated!", @"Information!",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, @"Error!",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Starts the connection.
        /// </summary>
        private void StartConnection()
        {
            _dbInboxService = new InboxServiceBase();
            _dbInboxNonService = new InboxNonServiceBase();
            _dbOutbox = new OutboxBase();
            _dbPassport = new XLPassportFormBase();
            _workflows = new WorkflowBase().GetAll();
        }

        /// <summary>
        /// Starts the gammu.
        /// </summary>
        private static void StartGammu()
        {

            if (!File.Exists("gammu.exe")) return;

            // starting gammu services
            var startInfo = new ProcessStartInfo("gammu.exe")
                                {
                                    WindowStyle = ProcessWindowStyle.Minimized,
                                    Arguments = "--smsd MYSQL smsdrc"
                                };

            Process.Start(startInfo);

        }

        /// <summary>
        /// Kills the gammu.
        /// </summary>
        private static void KillGammu()
        {
            Process[] ps = Process.GetProcessesByName("gammu");
            foreach (Process p in ps)
                p.Kill();
        }

        /// <summary>
        /// Timer1s the tick.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void Timer1Tick(object sender, EventArgs e)
        {
            txtLastStarted.Text = string.Format("{0} {1}", DateTime.Now.ToLongDateString(),
                                                DateTime.Now.ToLongTimeString());
            pnl1.BackColor = Color.Green;

            // Thread >> KILL
            var t = new Thread(KillGammu);
            t.Start();
            Thread.Sleep(1000);

            // Thread >> START
            t = new Thread(StartGammu);
            t.Start();
            Thread.Sleep(1000);

            // collect
            StartMessageProcessing();

            pnl1.BackColor = Color.Transparent;

            txtLastProcessed.Text = string.Format("{0} {1}", DateTime.Now.ToLongDateString(),
                                                  DateTime.Now.ToLongTimeString());
        }

        /// <summary>
        /// Starts the message processing.
        /// </summary>
        private void StartMessageProcessing()
        {
            // inboxs
            List<InboxService> inboxs = _dbInboxService.GetAllByRepliedStatus(false);

            // cek null inboxs)
            if (inboxs == null) return;

            // progress 1
            p1.Minimum = 0;
            p1.Maximum = inboxs.Count;
            p1.Value = 0;
            lblMessage.Text = string.Format("Ready");

            // for every row in inboxs
            foreach (InboxService msg in inboxs)
            {
                string wMsg = msg.Message.Trim();
                string wPhoneNo = msg.SenderNumber.Trim();
                string[] aMsg = wMsg.Split(' ');

                switch (aMsg[0].Trim().ToUpper())
                {
                    case "PASPOR":

                        // bila lebih dari 1 kata
                        if (aMsg.Length > 1)
                        {
                            // form no
                            string wFormNo = aMsg[1];

                            // ambil data namelist dari xlink
                            XLPassportForm passport = _dbPassport.GetById(wFormNo);

                            string wMsgReply;
                            string wNmKanim = Settings.Default.Kanim.Trim().Length > 30
                                                  ? Settings.Default.Kanim.Trim().Substring(0, 30)
                                                  : Settings.Default.Kanim.Trim();
                            try
                            {
                                string wWflDesc = "Belum ada informasi status";

                                // cari desc status
                                IEnumerable<Workflow> lqWfl = from r in _workflows
                                                              where
                                                                  r.WorkflowId == passport.WorkFlowXID.ToString().Trim()
                                                              select r;

                                foreach (Workflow r in lqWfl)
                                    wWflDesc = r.WorkflowDescription;

                                string wNmPassport = passport.Name.Trim().Length > 30
                                                         ? passport.Name.Trim().Substring(0, 30)
                                                         : passport.Name.Trim();

                                // format pesan balasan
                                wMsgReply =
                                    string.Format("Permh. a/n {0}, {1}. {2}",
                                                  wNmPassport, wWflDesc, wNmKanim);

                                ReplyMessage(wPhoneNo, wMsgReply);
                            }
                            catch (NullReferenceException)
                            {
                                // format pesan balasan
                                wMsgReply =
                                    string.Format("Permh. No.{0}, tidak ditemukan. {1}", wFormNo,
                                                  wNmKanim);

                                ReplyMessage(wPhoneNo, wMsgReply);
                            }
                        }
                        break;

                        /*case "KRITIK":

                        // bila lebih dari 1 kata
                        if (aMsg.Length > 1)
                        {
                            // pesan bila data ditemukan
                            string wMsgReply = string.Format("Terima kasih atas saran & kritik yang anda kirimkan. {0}",
                                                             Settings.Default.Kanim);
                            ReplyMessage(wPhoneNo, wMsgReply);
                        }
                        break;*/

                    default:

                        // pisahkan non service message
                        var ins = new InboxNonService
                                      {
                                          ID = msg.ID,
                                          SenderNumber = msg.SenderNumber,
                                          Message = msg.Message,
                                          IsReplied = false,
                                          ReceivingDateTime = msg.ReceivingDateTime
                                      };
                        _dbInboxNonService.SavePrimitive(ins);
                        break;
                }

                // progress
                p1.Value++;

                //msg
                lblMessage.Text = string.Format("Processing {0} of {1}", p1.Value, p1.Maximum);

                // update replied status
                _dbInboxService.UpdateRepliedStatus(msg.ID, true);
            }
        }

        /// <summary>
        /// Replies the message.
        /// </summary>
        /// <param name="wPhoneNo">The w phone no.</param>
        /// <param name="wMsgReply">The w MSG reply.</param>
        private void ReplyMessage(string wPhoneNo, string wMsgReply)
        {
            var obj = new Outbox {DestinationNumber = wPhoneNo, TextDecoded = wMsgReply};
            _dbOutbox.Save(obj);
        }

        /// <summary>
        /// Handles the Click event of the btnExit control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnExit_Click(object sender, EventArgs e)
        {
            tmrTime.Enabled = false;
            ShutdownApps();
        }

        /// <summary>
        /// Handles the Click event of the exitToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            KillGammu();
            tmrTime.Enabled = false;
            ShutdownApps();
        }

        /// <summary>
        /// Shutdowns the apps.
        /// </summary>
        private void ShutdownApps()
        {
            Close();
            Dispose();
            Application.Exit();
        }

        /// <summary>
        /// Handles the Click event of the restoreToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void restoreToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Show();
        }

        /// <summary>
        /// Handles the Click event of the toolStripMenuItem1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Hide();
        }

        /// <summary>
        /// Handles the Click event of the aboutMeToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void aboutMeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show(@"Copyright (C) 2010 Wish Enterprise",
                            @"Imigrasi SMS Autorespond v2.0", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        /// <summary>
        /// Handles the Click event of the mnuDbc control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void mnuDbc_Click(object sender, EventArgs e)
        {
            tmrTime.Enabled = false;
            using (var f = new DBLogonUI())
                f.ShowDialog(this);
            tmrTime.Enabled = true;
        }

        /// <summary>
        /// Handles the FormClosed event of the MainWindow control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.FormClosedEventArgs"/> instance containing the event data.</param>
        private void MainWindow_FormClosed(object sender, FormClosedEventArgs e)
        {
        }

        /// <summary>
        /// Handles the Click event of the btnReloadSmsdrc control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnReloadSmsdrc_Click(object sender, EventArgs e)
        {
            LoadSmsdrc();
        }

        /// <summary>
        /// Handles the Click event of the btnUpdateSmsdrc control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnUpdateSmsdrc_Click(object sender, EventArgs e)
        {
            UpdateSmsdrc();
        }

        /// <summary>
        /// Handles the FormClosing event of the MainWindow control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.FormClosingEventArgs"/> instance containing the event data.</param>
        private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            KillGammu();
        }
    }
}